Apple, the Apple logo, and Macintosh are registered trademarks of Apple Computer, Inc.
Mac and OpenDoc are trademarks of Apple Computer, Inc.
Embedding and Clipping
Containing parts manage the clipping of their embedded parts. Containing parts use the ClipShape of embedded facets to indicate how embedded parts should clip their drawing operations. A facet's ClipShape indicates which portion of the facet is visible within its containing facet. If the containing facet is itself obscured, that does not affect the embedded facet's ClipShape. To find out what portion of a facet is visible on its canvas, use ODFacet::GetAggregateClipShape.
At the risk of sounding tautalogical, a containing part needs to update its embedded facets' ClipShapes whenever the way they are clipped changes. There are a number of cases where that may happen: when content is rearranged or reformatted, when an embedded part is resized, when the active border shape moves from one frame to another, when selection handles are shown or hidden, when an embedded frame's UsedShape is changed. If the containing part does not allow embedded frames to be overlapped (like a text part), the number of situations requiring clipping will be minimal. If a containing part allows complex, overlapping arrangement of embedded frames, like a drawing or presentation part, then there will be many situations that require clipping.
Responsibilities
Containing Part
• Manage the ClipShape of embedded facets. Ensure embedded parts don't overwrite other parts, the containing part's intrinsic content, or the active border shape.
• Display in the portion of an embedded frame not included in the frame's UsedShape. The embedded part had guaranteed that it won't draw outside it's display frame's UsedShape, so the containing part has to do it.
Embedded Part
• Clip drawing operations to display facet's AggregateClipShape or WindowAggregateClipShape.
• Never draw outside of display frame's UsedShape (except root parts).
• If displaying asynchronously, update clipping when GeometryChanged notification indicates that the ClipShape has changed.
About the Sample Code
The code below follows a very simple recipe for clipping embedded facets. More sophisticated techniques are possible, and may be required for advanced imaging features such as translucency or compositing.
The basic recipe for clipping an embedded facet:
• Start with its FrameShape.
• Subtract from that the shapes of all the other facets and intrinsic content within the containing part that obscure the frame.
Some tips:
• When a facet is obscured by another facet, use the UsedShape of the obscuring facet's frame to clip the facet.
• Make sure that ALL intrinsic content is accounted for. This includes selection handles, active frame borders, frame adornments, etc. Anything that isn't an embedded frame but you don't want overwritten by an asynchronously displaying part (such as a clock or movie) must be included.
• If a containing part receives a UsedShapeChanged notification, you only need to re-clip the facets behind the changed one. That recipe is the same as the one below, but just start at the changed facet, not at the uppermost one. Same thing if the active border changes - just re-clip the facets behind the facet of the active frame (or the previously active frame).
CMyPart::GetFacetForEmbeddedContentItem()
Given a content object in the containing part, this method returns the embedded facet that needs to be clipped. If the containing part only allows one facet per embedded frame in each of its display frames, it doesn't need to store a pointer to the facet in the content object. In fact, that would be fairly confusing, and would just end up paralleling the facet list in the frame. Instead, this method will compute the intersection of the set of the immediate children of the containing part's display facet, and the set of the facets of the embedded frame. In that case, the intersection should be a single frame.
If a containing part allows multiple facets on an embedded frame in its content, it will need to keep an explicit reference to a facet in the content object. In that case, this method can just return that reference.